ChatGPTにプログラムコードを添削してもらおう! GPT-4o|Powered by AI-Starter

ChatGPTにプログラムコードを添削してもらおう! GPT-4o|Powered by AI-Starter

こんにちは!Koty-Mousa 矢坂幸太郎です。 前回は、ChatGPTで文章の添削をしてみました。このブログも添削してもらっていますよ!

https://dev.classmethod.jp/articles/koty-mousa-ai-correction-gpt-4o/

今回は、プログラムコードの添削です。 現在、研修でさまざまなプログラムコードを書いていますが、間違いを見つけるために利用しています。とても便利です。

コード添削

では、実際に試してみましょう。 今回は、私が(ChatGPTの協力で)用意した、意図的に間違いを含めたプログラムコードを利用します。

AI-Starterには、あらかじめ用意されたシステムプロンプトがあります。そのため、簡単に生成AIを利用できます。 もちろん、自分独自のプロンプトを利用することもできます。 今回は、AI-Starterにあらかじめ用意されているプロンプトに続いて、自分でプロンプトを作成しました。

プロンプトメッセージは下記の通りです

あなたは優秀なアシスタントです。ユーザーの指示には注意深く従ってください。
提示するプログラムがエラーを返します。理由と訂正されたプログラムを出力してください。

(斜体はAI-Starterに用意されているシステムプロンプト)

Java

//このコードは間違いを含んでいます
public class Main {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3};
        System.out.println(numbers[3]);
    }
}

このコードはエラーになります。さて、なぜでしょうか?
まずは自分で考えて、次にChatGPTに聞いてみましょう!

ChatGPTの回答です

このプログラムは、配列 numbers の存在しないインデックスにアクセスしようとしているため、実行時に ArrayIndexOutOfBoundsException が発生します。配列 numbers は3つの要素(インデックス0から2)しか持っていないため、インデックス3にアクセスするとエラーが発生します。

修正されたプログラムは、存在するインデックスにアクセスするように変更する必要があります。例えば、インデックス2にアクセスする場合は以下のようになります。

public class Main {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3};
        System.out.println(numbers[2]); // インデックス3ではなく2に変更
    }
}

この修正により、プログラムは正常に動作し、配列の最後の要素である 3 が出力されます。

理由まで解説してくれました! このミスは、私が専門学校生の頃によくやってしまったミスです。


次は、こちらのコードです。

//このコードには間違いを含んでいます
public class Main {
    public static void main(String[] args) {
        String str1 = new String("Hello");
        String str2 = new String("Hello");
        if (str1 == str2) {
            System.out.println("Strings are equal");
        } else {
            System.out.println("Strings are not equal");
        }
    }
}
//出力:Strings are not equal

str1とstr2は同じはずなのに、if文でfalseが返されました。おかしい。
ChatGPTに聞いてみましょう!

ChatGPTの回答

このプログラムはエラーを返していませんが、意図した結果が得られていないようです。具体的には、str1 == str2の比較がfalseを返すため、"Strings are not equal"が出力されます。

Javaでは、==演算子はオブジェクトの参照を比較します。つまり、str1とstr2が同じオブジェクトを参照しているかどうかを確認します。new String("Hello")を使用すると、異なるオブジェクトが作成されるため、str1 == str2はfalseになります。

文字列の内容を比較するには、equalsメソッドを使用する必要があります。以下に修正したプログラムを示します。

public class Main {
    public static void main(String[] args) {
        String str1 = new String("Hello");
        String str2 = new String("Hello");
        if (str1.equals(str2)) {
            System.out.println("Strings are equal");
        } else {
            System.out.println("Strings are not equal");
        }
    }
}

この修正により、str1とstr2の内容が比較され、"Strings are equal"が出力されるようになります。

素晴らしい!
これ、私もよくやってしまうミスで、専門学校では多くの人がこのミスを出した覚えがあります。 このプログラムはエラーが返されるわけではないので、プロンプトメッセージが不適切ですが、このまま利用しました。

ちなみに、もっとわかりやすく説明してもらうとどうなるでしょうか

クリックして表示

もう少しわかりやすく解説してくれますか?

もちろんです。もう少し詳しく解説します。

問題の原因

Javaでは、==演算子は以下のように動作します。

  • プリミティブ型(int, char, etc.)の場合:値を比較します。
  • 参照型(オブジェクト)の場合:オブジェクトの参照(メモリ上のアドレス)を比較します。

あなたのプログラムでは、Stringオブジェクトをnewキーワードを使って作成しています。この場合、str1str2は異なるオブジェクトを指しているため、==演算子を使うと異なる参照を比較することになります。

String str1 = new String("Hello");
String str2 = new String("Hello");

上記のコードでは、str1str2は異なるメモリ位置にある別々のオブジェクトです。そのため、str1 == str2falseを返します。

解決方法

文字列の内容を比較するためには、equalsメソッドを使用します。equalsメソッドは、オブジェクトの内容が等しいかどうかを比較します。

以下は修正したプログラムです:

public class Main {
    public static void main(String[] args) {
        String str1 = new String("Hello");
        String str2 = new String("Hello");
        if (str1.equals(str2)) {
            System.out.println("Strings are equal");
        } else {
            System.out.println("Strings are not equal");
        }
    }
}

動作の詳細

  1. new String("Hello")を使ってstr1str2を作成します。この時点で、str1str2は異なるオブジェクトを指しています。
  2. str1.equals(str2)を使用して、str1str2の内容を比較します。この場合、両方の文字列は「Hello」という同じ内容を持つため、equalsメソッドはtrueを返します。
  3. if文の条件がtrueになるため、"Strings are equal"が出力されます。

まとめ

  • ==演算子はオブジェクトの参照を比較します。
  • equalsメソッドはオブジェクトの内容を比較します。
  • 文字列の内容を比較する場合は、equalsメソッドを使用する必要があります。

このようにして、正しい比較が行われるようになります。

なるほど、理解できました。
ぜひ皆様も学習にAIをお役立てください。

Python

弊社の新卒研修で、Pythonを学んでおります。Pythonではどう解説してくれるでしょうか?

#このコードには間違いを含んでいます
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Alice", 30)

print(person["name"])
print(person["age"])

なぜエラーが発生するか、わかりましたか?
それではChatGPTに聞いてみましょう!

このコードには、Personクラスのインスタンスから属性にアクセスする方法に誤りがあります。Pythonでは、インスタンスの属性にはドット(.)を使ってアクセスしますが、コードでは辞書のようにブラケット([])を使ってアクセスしようとしています。

修正されたコードは以下の通りです:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Alice", 30)

print(person.name)
print(person.age)

この修正により、personオブジェクトのnameおよびage属性に正しくアクセスできるようになります。

ChatGPTによる詳しい解説はこちらをクリックして表示

もう少しわかりやすく解説してくれますか?

もちろんです。以下に、元のコードの問題点と修正方法について詳しく説明します。

元のコードの問題点

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Alice", 30)

print(person["name"])
print(person["age"])

このコードでは、Personクラスのインスタンスを作成し、そのインスタンスの属性にアクセスしようとしています。しかし、person["name"]person["age"]のように辞書のキーを使ってアクセスしようとしています。これはPythonのクラスインスタンスに対する正しいアクセス方法ではありません。

Pythonのクラスインスタンスの属性へのアクセス方法

Pythonでは、クラスの属性にアクセスするためにドット(.)を使います。例えば、personオブジェクトのname属性にアクセスするには、person.nameと書きます。同様に、age属性にはperson.ageと書きます。

修正されたコード

以下に修正されたコードを示します:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

person = Person("Alice", 30)

print(person.name)  # ドットを使ってname属性にアクセス
print(person.age)   # ドットを使ってage属性にアクセス

修正点の詳細

  1. クラス定義とインスタンス化

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    

    これは正しいです。Personクラスには__init__メソッドがあり、nameageの2つの属性を初期化します。

  2. インスタンスの作成

    person = Person("Alice", 30)
    

    これも正しいです。Personクラスのインスタンスを作成し、name属性に"Alice"、age属性に30を設定します。

  3. 属性へのアクセス

    print(person.name)  # ドットを使ってname属性にアクセス
    print(person.age)   # ドットを使ってage属性にアクセス
    

    ここが修正点です。person["name"]person["age"]と書くのではなく、person.nameperson.ageと書くことで、クラスインスタンスの属性に正しくアクセスできます。

この修正により、personオブジェクトのnameおよびage属性に正しくアクセスでき、エラーが解消されます。

こちらも同様に私のミスを元にしています。もちろん実行すればエラーが返されますが、正直それだけでは何が問題なのかわからないこともあります。私が学生の頃はひたすら忙しい先生に聞いていました。これからはわからないことはAIに聞くことも選択肢の一つとなりますね!

SQL

SELECT department_id, COUNT(*)
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 1 AND first_name = 'John';

これは...簡単かな?
慌てているとミスは起きるものです。なぜ間違っているのでしょうか?

このSQLクエリにはエラーがあります。HAVING句はグループ化された結果に対して条件を指定するために使用されますが、first_name = 'John'という条件は個々の行に対する条件であり、グループ化された結果に対して使用することはできません。

この場合、WHERE句を使用して、グループ化する前にfirst_name = 'John'という条件を適用する必要があります。

修正されたSQLクエリは以下の通りです:

SELECT department_id, COUNT(*)
FROM employees
WHERE first_name = 'John'
GROUP BY department_id
HAVING COUNT(*) > 1;

この修正により、まずWHERE句でfirst_name = 'John'という条件を適用し、その後でdepartment_idごとにグループ化し、カウントが1より大きいグループを取得します。

「なぜエラーがあるのか」を説明してもらうと、非常に大きな学びになります。
私が専門学校生の時にAI-Starterがあったらよかったのにな...

HTML/CSS

次は、HTML/CSSです。
HTMLの場合、「エラー」が出るというより「見た目がおかしい」ことが多いため、プロンプト文章をこちらに変更します。

このHTMLは、見た目がなんかおかしいです。理由と訂正されたプログラムを出力してください。

プロンプト文章に正解はありません。皆様も良いプロンプトを見つけてみてください。

こんなサイトを作ってみました。

スクリーンショット 2024-07-02 15.31.37
今のところこのサイトは存在しません。残念。

明らかに見た目がおかしいですね。
下のボタンの部分が崩れています。私が製作したときも、こういったことが時折発生しました。

現在のAI-Starterでは、画像を添付することができるので、上のスクリーンショットとHTML/CSSをChatGPTに送ります。
では、ChatGPTに修正してもらいましょう!

元のHTMLとCSSはこちらをクリックして表示

HTML

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Koty-Mousaファンクラブ</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container">
        <h1>Koty-Mousaファンクラブページ</h1>
        <form id="login-form">
            <div class="form-group">
                <label for="user-id">ユーザーID</label>
                <input type="text" id="user-id" name="user-id" required>
            </div>
            <div class="form-group">
                <label for="password">パスワード</label>
                <input type="password" id="password" name="password" required>
            </div>
            <button type="submit" class="btn btn-primary">ログイン</button>
        </form>
        <div class="button-group">
            <button class="btn btn-secondary" style="width: 50%;">Clamerusファンクラブへ</button>
            <button class="btn btn-tertiary" style="font-size: 14px;">利用規約</button>
        </div>
    </div>
</body>
</html>

CSS

body {
    font-family: Arial, sans-serif;
    background-color: #f0f0f0;
    margin: 0;
    padding: 0;
}

.container {
    max-width: 400px;
    margin: 2rem auto;
    padding: 2rem;
    background-color: #ffffff;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

h1 {
    text-align: center;
    color: #333;
    font-size: 1.5rem;
    margin-bottom: 2rem;
}

.form-group {
    margin-bottom: 1rem;
}

label {
    display: block;
    margin-bottom: 0.5rem;
    color: #666;
}

input[type="text"],
input[type="password"] {
    width: 100%;
    padding: 0.5rem;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 1rem;
}

.btn {
    display: inline-block;
    padding: 0.75rem;
    font-size: 1rem;
    text-align: center;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s;
    margin-bottom: 0.5rem;
}

.btn-primary {
    background-color: #4CAF50;
    color: white;
}

.btn-secondary {
    background-color: #2196F3;
    color: white;
}

.btn-tertiary {
    background-color: #FFC107;
    color: #333;
}

.btn:hover {
    opacity: 0.8;
}

.button-group {
    margin-top: 1rem;
}

回答はこちらです

回答はこちらをクリックして表示

このHTMLとCSSには特に大きな問題はありませんが、見た目をさらに整えるためにいくつかの改善点があります。以下に修正されたプログラムを示します。

修正点

  1. ボタンの幅とサイズを統一。
  2. ボタンのホバー効果を追加。
  3. フォームのレイアウトを改善。

修正されたHTML

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Koty-Mousaファンクラブ</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container">
        <h1>Koty-Mousaファンクラブページ</h1>
        <form id="login-form">
            <div class="form-group">
                <label for="user-id">ユーザーID</label>
                <input type="text" id="user-id" name="user-id" required>
            </div>
            <div class="form-group">
                <label for="password">パスワード</label>
                <input type="password" id="password" name="password" required>
            </div>
            <button type="submit" class="btn btn-primary">ログイン</button>
        </form>
        <div class="button-group">
            <button class="btn btn-secondary">Clamerusファンクラブへ</button>
            <button class="btn btn-tertiary">利用規約</button>
        </div>
    </div>
</body>
</html>

修正されたCSS

body {
    font-family: Arial, sans-serif;
    background-color: #f0f0f0;
    margin: 0;
    padding: 0;
}

.container {
    max-width: 400px;
    margin: 2rem auto;
    padding: 2rem;
    background-color: #ffffff;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

h1 {
    text-align: center;
    color: #333;
    font-size: 1.5rem;
    margin-bottom: 2rem;
}

.form-group {
    margin-bottom: 1rem;
}

label {
    display: block;
    margin-bottom: 0.5rem;
    color: #666;
}

input[type="text"],
input[type="password"] {
    width: 100%;
    padding: 0.5rem;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 1rem;
}

.btn {
    display: inline-block;
    width: 100%;
    padding: 0.75rem;
    font-size: 1rem;
    text-align: center;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    transition: background-color 0.3s;
    margin-bottom: 0.5rem;
}

.btn-primary {
    background-color: #4CAF50;
    color: white;
}

.btn-secondary {
    background-color: #2196F3;
    color: white;
}

.btn-tertiary {
    background-color: #FFC107;
    color: #333;
}

.btn:hover {
    opacity: 0.8;
}

.button-group {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-top: 1rem;
}

この修正により、ページの見た目がより一貫性を持ち、ユーザーインターフェースが使いやすくなります。

HTML/CSSをChatGPTの回答に置き換えると、こうなりました!
スクリーンショット 2024-07-03 11.30.22

すごーーーーーーい!
「だいたいできたのに、細かいところのせいでぐちゃぐちゃに...」という経験は幾度もあります。
これからは生成AIを良き相棒として私は成長します!

PR:AI-Starterって何?

本ブログで利用しているGPT-4oは、OpenAIのサイトからChatGPTを利用しているわけではありません。
クラスメソッドが法人向けに提供する生成AI環境構築サービス、AI-Starterを利用しております!
こちらは、クラスメソッドグループの社員も利用しております。
スクリーンショット 2024-07-03 13.33.11
ChatGPTだけではなく、Claude、Geminiといった、複数の生成AIサービスを1つのプラットフォームでシームレスに、そして安全に利用できるサービスです。
今回、プロンプト作りについて触れましたが、本サービスを用いれば社内でプロンプトを共有することもできるため、全社での生成系AIの利活用を推進できます!
「そもそもどんな業務に生成AIを活用できるかが分からない」という会社様も、ぜひ下記ページをご覧ください!
https://classmethod.jp/services/generative-ai/ai-starter/


最後に、とっても大切なこと

私、Koty-Mousaが考える大切なこと

それは、「次から同じミスをしないようにする」ことと、「AIに頼りきりにならない」ことです。

次から同じミスをしないようにする

今回は、私のミスをAIに修正してもらいました。より良い結果を提供するために、AIを利用することは非常に有用です。
しかしながら、それと同時に自らも成長する必要があると考えています。
ミスが少なくなれば、効率よく業務を遂行できます。ぜひ皆様も、自身のスキルアップに生成AIをお役立てください。

AIに頼りきらない

AI使用時の非常に重要な点として、「AIの出力をそのまま鵜呑みにしない」ことがあります。弊社ガイドラインには『文章生成AIが生成する文章は、内容が正しくない場合があることを認識して利用すること』と記載があります。
現在、GPT-4oをはじめ多くの生成AIは非常に良い結果を返していますが、時に正しくない結果を返すことがあります。
私が時々遭遇するのは、「プロンプト文・指示が不明瞭なため、AIが指示を誤った解釈をしてしまった」ことです。
AIの出力は、問題がないことをご自身で確認の上、利用するようにしましょう。

弊社内ガイドラインは、下記ブログをご覧ください
https://dev.classmethod.jp/articles/guideline-for-use-of-ai-services/

私は生成AIを「自分の成長のための よき相棒」と考えています。

Koty-Mousa 矢坂幸太郎がお伝えしました。


The avatar, logo and name of "Koty-Mousa 矢坂幸太郎" and "Clamerus, dev. by Koty-Mousa" (include inconsistent/abbreviation spelling) are owned and copyrighted by Koty-Mousa (individually). "YASAKA Hall" by Koty-Mousa. Untitled song by Clamerus.

アノテーション株式会社について

アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.